module mculib.baremetal.stdlib;


import ldc.intrinsics;
import std.traits;


pragma(LDC_no_moduleinfo):
private{
    /// 根据类型size推导出对应的类型
    template TypeOfSize(size_t size)
    {
        static if(size == 1) alias TypeOfSize = ubyte;
        else static if(size == 2) alias TypeOfSize = ushort;
        else static if(size == 4) alias TypeOfSize = uint;
        else static if(size == 8) alias TypeOfSize = ulong;
        else static assert(0,"not supported");
    }
}

version(FreeStanding)
{
    version(LDC){
        pragma(LDC_alloca) void* alloca(size_t size) pure;
    }else version(GNU){

    }else{
        static assert(0,"not supported");
    }

    /**
        复制
        Params:
            dst = 目标
            src = 源
    */
    // 内置类型复制
    pragma(inline,true)
    void memcpyD(T)(ref T dst,ref T src) pure nothrow @nogc
    if(isScalarType!T)
    {
        dst = src;
    }
    // 转换到内置类型
    pragma(inline,true)
    void memcpyD(T)(ref T dst,ref T src) pure nothrow @nogc
    if(is(T == struct))
    {
        alias mType = TypeOfSize!T.sizeof;
        memcpyD(*cast(mType*)(&dst), *cast(const mType*)(&src));
    }
    /**
    * 赋值,需要值类型与数组类型相同
    * Params:
    *    dst = 目标
    *    val = 值
    */
    pragma(inline,true)
    void memsetD(T,S)(ref T dst,S val) pure nothrow @nogc 
    if((isArray!T) && (isScalarType!(ForeachType!T)) && is(ForeachType!T == S))
    {
        foreach(ref v;dst)
        {
            v = val;
        }
    }
    // 指针地址赋值,需要指针类型的`sizeof`
    // 对数组内存进行赋值
    void memsetD(T)(ref T dst,ubyte val) @system @nogc
    if((isArray!T))
    {
        //enum asize = (PointerTarget!T).sizeof * dst.length;
        enum asize = (ForeachType!T).sizeof * dst.length;
        //
        memset(dst.ptr,val,asize);
    }
    

      

    // 断言
    
    //extern(C) @system @nogc nothrow 
    //void __assert(const(char)* exp,const(char)* file,uint line)
    extern (C) 
    void __assert(const char* msg_, const char* file_, int line) @trusted
    {
        while(1){
            asm{"wfi";}
        }
    }
    

}

extern(C)
{
    import core.attribute:optStrategy;
    /**
    *    复制数据到目标,自行检查匹配字节的size
    *    Params:
    *        dst = 目标
    *        src = 源
    *        n = 复制长度
    */
    @optStrategy("optsize") @system
    void* memcpy(return scope void* dst,scope const void* src,size_t n) @nogc 
    {
        //处理宽度
        enum width = size_t.sizeof;

        auto dp = cast(ubyte*)dst;
        auto sp = cast(ubyte*)src;
        // 优先处理32位
        for(;n>4;n-=4)
        {
            *cast(uint*)dp = *cast(uint*)sp;
            dp += 4;
            sp += 4;
        }
        // 处理未完成部分
        while(n--)
        {
            *dp++ = *sp++;
        }
        return dst;
    }
    /**
    *   对目标进行赋值,自行检查匹配字节的size
    *   Params:
    *       ptr = 目标
    *       c = 字节值
    *      n = 赋值长度
    */
    @optStrategy("optsize") @system
    void* memset(return scope void* ptr, ubyte c, size_t n) @nogc nothrow
    {
        //处理宽度
        enum width = size_t.sizeof;
        auto pp = cast(ubyte*)ptr;
        uint c4 = c | (c << 8) | (c << 16) | (c << 24);
        // 优先处理32位
        for(;n>4;n-=4)
        {
            *cast(uint*)pp = c4;
            pp += 4;
        }
        // 处理未完成部分
        while(n--)
        {
            *pp++ = cast(ubyte)c;
        }
        return ptr;
    }


}